/*
 * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *   * Neither the name of Intel Corporation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "Enclave.h"
#include "Enclave_t.h" /* print_string */
#include <stdarg.h>
#include <stdio.h> /* vsnprintf */
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <time.h>
#include <stdint.h>

// #include <stdint.h>
// #include <openssl/aes.h>

#include "sgx_trts.h"
#include "sgx_tcrypto.h"
#include <cstring>

#define AES_CMAC_BLOCK_SIZE 16
#define CMAC_KEY_SIZE 16
#define MESSAGE_SIZE 16

const double TSC_FREQUENCY = 2.3e9;
double time = 0.0;

using namespace std;

static inline uint64_t get_rdtsc() {
    uint32_t hi, lo;
    __asm__ __volatile__ (
        "rdtsc" : "=a"(lo), "=d"(hi)
    );
    return ((uint64_t)hi << 32) | lo;
}



/* 
 * printf: 
 *   Invokes OCALL to display the enclave buffer to the terminal.
 */
int printf(const char* fmt, ...)
{
    char buf[BUFSIZ] = { '\0' };
    va_list ap;
    va_start(ap, fmt);
    vsnprintf(buf, BUFSIZ, fmt, ap);
    va_end(ap);
    ocall_print_string(buf);
    return (int)strnlen(buf, BUFSIZ - 1) + 1;
}

void enclave_increment_array(int array[5], int len){
    for(int i=0; i<len; i++){
        printf("%d\n", array[i]);
    }
    for(int i=0; i<len; i++){
        array[i] = array[i]*2;
    }
    for(int i=0; i<len; i++){
        printf("%d\n", array[i]);
    }
}

void ecall_sum(int array[1000000], int len){
    printf("flag");
    int sum = 0;
    for(int i=0; i<len; i++){
        sum += array[i];
    }
    printf("%d\n", sum);
}

void ecall_calculate(){

    vector<int> a{1,2,3,4,5};
    sort(a.begin(), a.end(), greater<int>());
    vector<int>::iterator it;
    for(it = a.begin(); it != a.end(); it++){
        printf("%d\n", *it);
    }

}

int cal_prime(){
    int i,j,k=0;
    for(i=2; i<10000; i++){
        for(j=2; j*j<=i; j++){
            if(i%j == 0)
                break;
        }
        if(j*j > i){
            k++;
        }
    }
    return k;
}

sgx_cmac_128bit_tag_t result = {0};
sgx_cmac_128bit_tag_t readSet = {0};
sgx_cmac_128bit_tag_t writeSet = {0};
sgx_cmac_128bit_tag_t writeSet_v = {0};
uint8_t key[16] = {0};
  
void sgx_error_handler(sgx_status_t ret) 
{
    if (ret != SGX_SUCCESS) {
        printf("SGX error\n");
    }
}

void ecall_write_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet[i] ^= cmac_result[i];
    }

    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");
}

void ecall_read_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet[i] ^= cmac_result[i];
        readSet[i] ^= cmac_result[i];
    }

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");
    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");
}

void ecall_delete_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        readSet[i] ^= cmac_result[i];
    }
}

void ecall_read_verify(const char* str, size_t str_len)
{
    printf("data:%s",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet_v[i] ^= cmac_result[i];
        readSet[i] ^= cmac_result[i];
    }

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");
}

void ecall_verify(int* result)
{
    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");


    *result = (memcmp(readSet, writeSet, sizeof(sgx_cmac_128bit_tag_t)) == 0) ? 1:0;

    if (sizeof(writeSet) == sizeof(writeSet_v)) {
        for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
            writeSet[i] ^= writeSet_v[i];
        }
    } else {
        printf("error!\n");
        // 处理错误，可能需要打印错误信息或者采取其他适当的措施
    }
    memset(writeSet_v, 0, sizeof(sgx_cmac_128bit_tag_t));
}

void read_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet[i] ^= cmac_result[i];
        readSet[i] ^= cmac_result[i];
    }

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");

    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");
}

void write_db(const char* str, size_t str_len)
{
    printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet[i] ^= cmac_result[i];
    }

    printf("Write Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSet[i]);
    }
    printf("\n");
}

void read_verify(const char* str, size_t str_len)
{
    printf("data:%s",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSet_v[i] ^= cmac_result[i];
        readSet[i] ^= cmac_result[i];
    }

    printf("Read Set: ");
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSet[i]);
    }
    printf("\n");
}

// void verify(int* result)
// {
//     *result = (memcmp(readSet, writeSet, sizeof(sgx_cmac_128bit_tag_t)) == 0) ? 1:0;

//     if (sizeof(writeSet) == sizeof(writeSet_v)) {
//         for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
//             writeSet[i] ^= writeSet_v[i];
//         }
//     } else {
//         printf("error!\n");
//         // 处理错误，可能需要打印错误信息或者采取其他适当的措施
//     }
//     memset(writeSet_v, 0, sizeof(sgx_cmac_128bit_tag_t));
// }

// 获取时间戳计数器（TSC）的值
uint64_t get_tsc_value() {
    uint32_t eax, edx;
    __asm__ __volatile__("rdtsc" : "=a"(eax), "=d"(edx));
    return ((uint64_t)edx << 32) | eax;
} 

TableIdPair tableIdDict[8] = {
    {"customer", 0},
    {"lineitem", 1},
    {"nation", 2},
    {"orders", 3},
    {"part", 4},
    {"partsupp", 5},
    {"region", 6},
    {"supplier", 7}
};

int getTableId(char* table) 
{
    for (int i = 0; i < 8; i++) {
        if (strcmp(tableIdDict[i].table, table) == 0) {
            return tableIdDict[i].id;
        }
    }
    return -1; // 未找到
}

char* getTableById(int id) 
{
    for (int i = 0; i < 8; i++) {
        if (tableIdDict[i].id == id) {
            return tableIdDict[i].table;
        }
    }
    return NULL; // 未找到
}

sgx_cmac_128bit_tag_t results = {{0}};
sgx_cmac_128bit_tag_t readSets[8] = {{0}};
sgx_cmac_128bit_tag_t writeSets[8] = {{0}};
sgx_cmac_128bit_tag_t writeSets_v[8] = {{0}};
bool verifyFlags[8] = {true};
// uint8_t key[16] = {0};

void printReadSet(int id)
{
    printf("Read Set %d: ", id);
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", readSets[id][i]);
    }
    printf("\n");
}

void printWriteSet(int id)
{
    printf("Write Set %d: ", id);
    for (int i=0; i<sizeof(sgx_cmac_128bit_tag_t); i++){
        printf("%02X", writeSets[id][i]);
    }
    printf("\n");
}

void readDB(const char* str, size_t str_len, int id)
{
    // printf("data:%s\n",str);
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSets[id][i] ^= cmac_result[i];
        readSets[id][i] ^= cmac_result[i];
    }

    verifyFlags[id] = false;
}

void writeDB(const char* str, size_t str_len, int id)
{
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSets[id][i] ^= cmac_result[i];
    }

    verifyFlags[id] = false;
}

void read4verify(const char* str, size_t str_len, int id)
{
    sgx_cmac_128bit_tag_t cmac_result;
    sgx_status_t ret;

    // 计算CMAC
    ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t*)key, (uint8_t*)str, str_len, &cmac_result);
    sgx_error_handler(ret);

    // 异或结果
    for (size_t i = 0; i < sizeof(sgx_cmac_128bit_tag_t); ++i) {
        writeSets_v[id][i] ^= cmac_result[i];
        readSets[id][i] ^= cmac_result[i];
    }
}

void verify()
{
    for(int i=0; i<1; i++) {
        if(verifyFlags[i]) {
            continue;
        } else {
            char sql[MAX_SQL_LENGTH] = "select * from ";
            strncat(sql, getTableById(i), MAX_SQL_LENGTH);
            int cnt = 0;
            ocall_verify(sql, &cnt, MAX_RECORD_LENGTH);
            printf("cnt:%d\n",cnt);
            for(int j=0; j<cnt; j++) {
                // if(j%5000 == 0)     printf("%d\n",j);
                char record[MAX_RECORD_LENGTH]; 
                enclave_get_verify_record(j, record, MAX_RECORD_LENGTH);
                read4verify(record, sizeof(record), i); 
            }
            // ocall_free_res();
            bool flag = (memcmp(readSets[i], writeSets[i], sizeof(sgx_cmac_128bit_tag_t)) == 0) ? true:false;
            if(!flag){
                if (sizeof(writeSets[i]) == sizeof(writeSets_v[i])) {
                    for (size_t k = 0; k < sizeof(sgx_cmac_128bit_tag_t); ++k) {
                        writeSets[i][k] ^= writeSets_v[i][k];
                    }
                } else {
                    printf("error!\n");
                    // 处理错误，可能需要打印错误信息或者采取其他适当的措施
                }
                memset(writeSets_v[i], 0, sizeof(sgx_cmac_128bit_tag_t));
                continue;
            } else {
                printf("verify failed!\n");
                return;
            }
        }
    }
    for(int i=0; i<8; i++) {
        printReadSet(i);
        printWriteSet(i);
    }
    printf("verify succeed!\n");
}

FieldTypePair fieldTypeDict[MAX_ENTRIES];
int dictSize = 0;

// 添加键值对
void addEntry(const char* field, const char* type) 
{
    if (dictSize >= MAX_ENTRIES) {
        printf("Dictionary is full!\n");
        return;
    }
    strncpy(fieldTypeDict[dictSize].field, field, MAX_KEY_LEN);
    strncpy(fieldTypeDict[dictSize].type, type, MAX_VALUE_LEN);
    dictSize++;
}

// 查找键对应的值
char* getType(char* field) 
{
    for (int i = 0; i < dictSize; i++) {
        if (strcmp(fieldTypeDict[i].field, field) == 0) {
            return fieldTypeDict[i].type;
        }
    }
    return NULL; // 未找到
}

void initTypeDict() 
{
    addEntry("l_orderkey","int");
    addEntry("o_orderdate","date");
    addEntry("o_shippriority","int");
    addEntry("sum(l_extendedprice * (1 - l_discount))","float");
    addEntry("province","varchar");
    addEntry("age","int");
}

int parse_record(char* record, char (*row)[MAX_FIELD_LENGTH]) 
{
    // uint64_t start = get_rdtsc(); 
    char* token;
    char* tempString = strndup(record, MAX_RECORD_LENGTH);
    int num = 0;

    token = strtok(tempString, "|");
    while (token != NULL && num < MAX_FIELD_LENGTH) {
        strlcpy(row[num], token, MAX_FIELD_LENGTH);
        num++;
        token = strtok(NULL, "|");
    }

    free(tempString);
    //     uint64_t end = get_rdtsc();
    // time += (end - start) / TSC_FREQUENCY;
    return num;
}

int execute_join(char* outer_query, char* inner_query, const char* join_col1, const char* join_col2, 
                    int id1, int id2, int outputNum, char (*output)[MAX_FIELD_LENGTH], Page* result)
{
    int outer_cnt=0, inner_cnt=0;
    char outer_fields_record[MAX_RECORD_LENGTH];
    char inner_fields_record[MAX_RECORD_LENGTH];

    strncat(outer_query, " order by ", MAX_SQL_LENGTH);
    strncat(outer_query, join_col1, MAX_SQL_LENGTH);
    strncat(inner_query, " order by ", MAX_SQL_LENGTH);
    strncat(inner_query, join_col2, MAX_SQL_LENGTH);

    printf("%s\n", outer_query);
    printf("%s\n", inner_query);
    // 在此处调用Enclave外部的函数，将SQL语句传递给Enclave外部执行
    ocall_outer_loop(outer_query, &outer_cnt, outer_fields_record, MAX_RECORD_LENGTH);
    ocall_inner_loop(inner_query, &inner_cnt, inner_fields_record, MAX_RECORD_LENGTH);

    char outer_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
    char inner_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  

    int outer_field_cnt = parse_record(outer_fields_record, outer_fields);
    int inner_field_cnt = parse_record(inner_fields_record, inner_fields);

    int* output_field = (int *)malloc(outputNum * sizeof(int));
    int field_cnt = 0;

    for(int i=0; i<outputNum; i++) {
        for(int j=0; j<outer_field_cnt; j++) {
            if(!strcmp(output[i], outer_fields[j])){
                strncat(result->record[0], outer_fields[j], MAX_FIELD_LENGTH);
                strncat(result->record[0], "|", MAX_FIELD_LENGTH);
                output_field[field_cnt] = j;
                field_cnt ++;
            }
        }
        for(int j=0; j<inner_field_cnt; j++) {
            if(!strcmp(output[i], inner_fields[j])){
                strncat(result->record[0], inner_fields[j], MAX_FIELD_LENGTH);
                strncat(result->record[0], "|", MAX_FIELD_LENGTH);
                output_field[field_cnt] = outer_field_cnt+j;
                field_cnt ++;
            }
        }
    }

    int outer_id=0, inner_id=0;
    for(int i=0; i<outer_field_cnt; i++) {
        if(!strcmp(join_col2, outer_fields[i])) {
            outer_id = i;
        }
    }
    for(int i=0; i<inner_field_cnt; i++) {
        if(!strcmp(join_col1, inner_fields[i])) {
            inner_id = i;
        }
    }

    printf("outer id: %d\n", outer_id);
    printf("inner id: %d\n", inner_id);

    char **outer_table = (char **)malloc(outer_cnt * sizeof(char *));
    if (outer_table == NULL) {
        printf("内存分配失败1\n");
    }
    for (int i = 0; i < MAX_ROW_NUM; i++) {
        outer_table[i] = (char *)malloc(MAX_RECORD_LENGTH * sizeof(char));
        if (outer_table[i] == NULL ) {
            printf("内存分配失败2\n");
        }
    }

    int result_cnt = 1;
    const char delimiter[] = "|";
    printf("inner count:%d\n", inner_cnt);
    printf("outer count:%d\n", outer_cnt);

    char inner_record[MAX_RECORD_LENGTH]; 

    int page_num = (outer_cnt+MAX_ROW_NUM-1)/MAX_ROW_NUM;
    printf("page_num:%d\n",page_num);
    int out_ptr=0, in_ptr=0;

    for(int t=0; t<page_num-1; t++) {
        printf("page_id:%d\n",t);
        for(int i=0; i<MAX_ROW_NUM; i++) {
            uint64_t start = get_rdtsc(); 
            enclave_get_outer_record(i+t*MAX_ROW_NUM, outer_table[i], MAX_RECORD_LENGTH);
            uint64_t end = get_rdtsc();
            time += (end - start) / TSC_FREQUENCY;
            readDB(outer_table[i], sizeof(outer_table[i]), id2);
        }
        out_ptr=0;
        uint64_t start = get_rdtsc(); 
        enclave_get_inner_record(in_ptr, inner_record, MAX_RECORD_LENGTH);
        uint64_t end = get_rdtsc();
        time += (end - start) / TSC_FREQUENCY;
        readDB(inner_record, sizeof(inner_record), id1);
        char outer_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0}; 
        char inner_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH];  
        int inner_index = 0, outer_index = 0;
        while(out_ptr < MAX_ROW_NUM) {
            if(result_cnt >= MAX_ROW_NUM) {
                printf("%d\n", result_cnt);
            }
            outer_index = parse_record(outer_table[out_ptr], outer_row);
            inner_index = parse_record(inner_record, inner_row);
            if(atoi(outer_row[outer_id]) == atoi(inner_row[inner_id])){
                for(int k=0; k<outputNum; k++) {
                    if(output_field[k]<outer_field_cnt) {
                        strncat(result->record[result_cnt], outer_row[output_field[k]], MAX_FIELD_LENGTH);
                        strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                    } else {
                        strncat(result->record[result_cnt], inner_row[output_field[k]-outer_field_cnt], MAX_FIELD_LENGTH);
                        strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                    }
                }
                result_cnt++;
                out_ptr++;
            } else if(atoi(outer_row[outer_id]) < atoi(inner_row[inner_id])) {
                out_ptr++;
                continue;
            } else if(atoi(outer_row[outer_id]) > atoi(inner_row[inner_id])) {
                in_ptr++;
                if(in_ptr < inner_cnt) {
                    uint64_t start = get_rdtsc(); 
                    enclave_get_inner_record(in_ptr, inner_record, MAX_RECORD_LENGTH);
                    uint64_t end = get_rdtsc();
                    time += (end - start) / TSC_FREQUENCY;
                    readDB(inner_record, sizeof(inner_record), id1);
                    continue;
                } else {
                    break;
                }
            }
        }
    }
    
    //for the last page
    int last_page_num = outer_cnt - (page_num-1)*MAX_ROW_NUM;
    printf("last_page_num:%d\n",last_page_num);
    for(int i=0; i<last_page_num; i++) {
        enclave_get_outer_record(i+(page_num-1)*MAX_ROW_NUM, outer_table[i], MAX_RECORD_LENGTH);
        readDB(outer_table[i], sizeof(outer_table[i]), id2);
    }
    out_ptr = 0;
    enclave_get_inner_record(in_ptr, inner_record, MAX_RECORD_LENGTH);
    // printf("%s\n", inner_record);
    readDB(inner_record, sizeof(inner_record), id1);
    char outer_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0}; 
    char inner_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH];  
    int inner_index = 0, outer_index = 0;
    while(out_ptr < last_page_num) {
        if(result_cnt >= MAX_ROW_NUM) {
            printf("result overflow:%d\n", result_cnt);
        }
        outer_index = parse_record(outer_table[out_ptr], outer_row);
        inner_index = parse_record(inner_record, inner_row);
        // printf("row:%s, %s\n", outer_row[0], inner_row[0]);
        if(strncmp(outer_row[outer_id],inner_row[inner_id],MAX_FIELD_LENGTH) == 0){
        // if(atoi(outer_row[outer_id]) == atoi(inner_row[inner_id])){
            printf("%s, %s\n", outer_row[outer_id],inner_row[inner_id]);
            for(int k=0; k<outputNum; k++) {
                if(output_field[k]<outer_field_cnt) {
                    strncat(result->record[result_cnt], outer_row[output_field[k]], MAX_FIELD_LENGTH);
                    strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                } else {
                    strncat(result->record[result_cnt], inner_row[output_field[k]-outer_field_cnt], MAX_FIELD_LENGTH);
                    strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                }
            }
            result_cnt++;
            out_ptr++;
        } else if(strncmp(outer_row[outer_id],inner_row[inner_id],MAX_FIELD_LENGTH) < 0) {
        // } else if(atoi(outer_row[outer_id]) < atoi(inner_row[inner_id])) {
            out_ptr++;
            continue;
        } else if(strncmp(outer_row[outer_id],inner_row[inner_id],MAX_FIELD_LENGTH) > 0) {
        // } else if(atoi(outer_row[outer_id]) > atoi(inner_row[inner_id])) {
            in_ptr++;
            if(in_ptr < inner_cnt) {
                enclave_get_inner_record(in_ptr, inner_record, MAX_RECORD_LENGTH);
                readDB(inner_record, sizeof(inner_record), id1);
                continue;
            } else {
                break;
            }
        }
    }

    printf("Result cnt:%d\n",result_cnt);
    printReadSet(id1);
    printWriteSet(id1);
    printReadSet(id2);
    printWriteSet(id2);

    return result_cnt;
}

// int execute_join_with_midres(int outer_cnt, char (*midres)[MAX_RECORD_LENGTH], const char* inner_query, 
//                              const char* join_col, char (*result)[MAX_RECORD_LENGTH])
int execute_join_with_midres(int outer_cnt, Page* midres, const char* inner_query, const char* join_col1, const char* join_col2, 
                                int id, int outputNum, char (*output)[MAX_FIELD_LENGTH], Page* result)                             
{
    int inner_cnt=0;
    char inner_fields_record[MAX_RECORD_LENGTH];
    ocall_inner_loop(inner_query, &inner_cnt, inner_fields_record, MAX_RECORD_LENGTH);
    char* outer_fields_record = midres->record[0];
    // printf("%s\n", outer_fields_record);
    // printf("fields: %s\n", result->record[0]);

    char outer_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
    char inner_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  

    int outer_field_cnt = parse_record(outer_fields_record, outer_fields);
    int inner_field_cnt = parse_record(inner_fields_record, inner_fields);

    int* output_field = (int *)malloc(outputNum * sizeof(int));
    int field_cnt = 0;

    for(int i=0; i<outputNum; i++) {
        for(int j=0; j<outer_field_cnt; j++) {
            if(!strcmp(output[i], outer_fields[j])){
                strncat(result->record[0], outer_fields[j], MAX_FIELD_LENGTH);
                strncat(result->record[0], "|", MAX_FIELD_LENGTH);
                output_field[field_cnt] = j;
                field_cnt ++;
            }
        }
        for(int j=0; j<inner_field_cnt; j++) {
            if(!strcmp(output[i], inner_fields[j])){
                strncat(result->record[0], inner_fields[j], MAX_FIELD_LENGTH);
                strncat(result->record[0], "|", MAX_FIELD_LENGTH);
                output_field[field_cnt] = outer_field_cnt+j;
                field_cnt ++;
            }
        }
    }
    printf("fields: %s\n", result->record[0]);
    // printf("join_col2:%s\n", join_col2);

    int outer_id=0, inner_id=0;
    for(int i=0; i<outer_field_cnt; i++) {
        if(!strcmp(join_col1, outer_fields[i])) {
            outer_id = i;
        }
    }
    for(int i=0; i<inner_field_cnt; i++) {
        if(!strcmp(join_col2, inner_fields[i])) {
            inner_id = i;
        } 
    }

    printf("inner id:%d\n", inner_id);
    printf("outer id:%d\n", outer_id);

    char outer_record[MAX_RECORD_LENGTH];
    char inner_record[MAX_RECORD_LENGTH];

    int result_cnt = 1;

    const char delimiter[] = "|";
    printf("inner count2:%d\n", inner_cnt);
    printf("outer count2:%d\n", outer_cnt);
    for(int i=1; i<outer_cnt; i++){
        strlcpy(outer_record, midres->record[i], MAX_RECORD_LENGTH);        
        
        // printf("out record:%d\n",i);

        // 创建一个足够大的数组来存储分割后的子字符串
        char outer_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
        int outer_index = 0;
        outer_index = parse_record(outer_record, outer_row);

        for(int j=0; j<inner_cnt; j++){     
            enclave_get_inner_record(j, inner_record, MAX_RECORD_LENGTH);
            readDB(inner_record, sizeof(inner_record), id);
            
            char inner_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH];  // 假设每个子字符串不超过 100 个字符，最多分割 100 次
            int inner_index = 0;
            inner_index = parse_record(inner_record, inner_row);

            if(strncmp(outer_row[outer_id], inner_row[inner_id], MAX_FIELD_LENGTH) == 0){
                for(int k=0; k<outputNum; k++) {
                    if(output_field[k]<outer_field_cnt) {
                        strncat(result->record[result_cnt], outer_row[output_field[k]], MAX_FIELD_LENGTH);
                        strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                    } else {
                        strncat(result->record[result_cnt], inner_row[output_field[k]-outer_field_cnt], MAX_FIELD_LENGTH);
                        strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                    }
                }
                result_cnt++;
            }
        }
    }

    printReadSet(id);
    printWriteSet(id);

    return result_cnt;
}

// 这个函数还是最初版的，因为暂时用不到，用的时候需要修改到和上面两个函数同步
int execute_join_with_midres2(int outer_cnt, char (*midres1)[MAX_RECORD_LENGTH], int outer_id,
                              int inner_cnt, char (*midres2)[MAX_RECORD_LENGTH], int inner_id,
                              char (*result)[MAX_RECORD_LENGTH])
{
    char outer_record[MAX_RECORD_LENGTH];
    char inner_record[MAX_RECORD_LENGTH];

    int result_cnt = 1;

    const char delimiter[] = "|";
    for(int i=1; i<outer_cnt; i++){
        strlcpy(outer_record, midres1[i], MAX_RECORD_LENGTH);
        
        // 创建一个足够大的数组来存储分割后的子字符串
        char outer_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
        int outer_index = 0;
        outer_index = parse_record(outer_record, outer_row);

        for(int j=1; j<inner_cnt; j++){
            // enclave_get_inner_record(j, inner_record, MAX_RECORD_LENGTH);
            strlcpy(inner_record, midres2[i], MAX_RECORD_LENGTH);
            
            char inner_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH];  // 假设每个子字符串不超过 100 个字符，最多分割 100 次
            int inner_index = 0;
            inner_index = parse_record(inner_record, inner_row);

            if(strncmp(outer_row[outer_id], inner_row[inner_id], MAX_FIELD_LENGTH) == 0){
                for(int k=0; k<outer_index; k++){
                    strncat(result[result_cnt], outer_row[k], MAX_FIELD_LENGTH);
                    strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                }
                for(int k=0; k<inner_index; k++){
                    strncat(result[result_cnt], inner_row[k], MAX_FIELD_LENGTH);
                    strncat(result[result_cnt], "|", MAX_FIELD_LENGTH);
                }
                result_cnt++;
            }
        }
    }
    return result_cnt;
}

// 结构体，用于传递排序关键列信息
// typedef struct {
//     int *sortKeys;
//     int sortKeyNum;
//     bool *asc;
// } SortContext;

int execute_sort(int midres_cnt, Page* midres, int sortKeyNum, char (*sortKey)[MAX_FIELD_LENGTH], 
                    int outputNum, char (*output)[MAX_FIELD_LENGTH], Page* result)                             
{
    char inner_fields_record[MAX_RECORD_LENGTH];
    // strncpy(inner_fields_record, midres->record[0], MAX_RECORD_LENGTH);
    // printf("fields:%s, %d\n", fields, midres_cnt);
    strncpy(result->record[0], midres->record[0], MAX_RECORD_LENGTH);
    char* fields = midres->record[0];
    // strncpy(result->record[0],fields, MAX_RECORD_LENGTH);
    // printf("fields:%s, %d\n", fields, midres_cnt);
    // printf("record:%s\n", midres->record[1]);
    
    char out_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
    int fields_num = parse_record(fields, out_fields);

    int* sortkey_field = (int *)malloc(sortKeyNum * sizeof(int));
    int* order = (int *)malloc(sortKeyNum * sizeof(int));
    int field_cnt = 0;
    bool* asc = (bool *)malloc(sortKeyNum * sizeof(bool));

    for(int i=0; i<fields_num; i++) {
        printf("fields:%s\n", out_fields[i]);
    }

    for(int i=0; i<sortKeyNum; i++) {
        // printf("sortKey:%s\n", sortKey[i]);
        char* match = strstr(sortKey[i], " DESC");
        if(match) {
            asc[i] = false;
            *match = '\0';
        } else {
            asc[i] = true;
        }

        size_t len = strlen(sortKey[i]);
        // 判断首尾是否为括号
        if (sortKey[i][0] == '(' && sortKey[i][len - 1] == ')') {
            // 将字符串整体左移一位，并在末尾添加空字符
            memmove(sortKey[i], sortKey[i] + 1, len - 1);
            sortKey[i][len - 2] = '\0'; // 设置新的字符串结尾
        }

        for(int j=0; j<fields_num; j++) {
            if(!strcmp(sortKey[i], out_fields[j])){
                sortkey_field[field_cnt] = j;
                field_cnt ++;
            }
        }
    }

    for(int i=0; i<sortKeyNum; i++) {
        printf("sortKey:%d\n", sortkey_field[i]);
        printf("sortKey:%s\n", sortKey[i]);
        // printf("%d\n", strlen(sortKey[i]));
    }
    // printf("join_col1:%s\n", join_col1);
    // printf("join_col2:%s\n", join_col2);

    char record[MAX_ROW_NUM][MAX_FIELD_NUM][MAX_FIELD_LENGTH];

    char outer_record[MAX_RECORD_LENGTH];
    char inner_record[MAX_RECORD_LENGTH];
    // uint64_t start = get_rdtsc(); 
    printf("midres_cnt: %d\n", midres_cnt);
    printf("midres: %s\n", midres[1]);
    for(int i=1; i<midres_cnt; i++){
        for(int j=1; j<midres_cnt-i; j++){     
            strlcpy(outer_record, midres->record[j], MAX_RECORD_LENGTH);
            // // 创建一个足够大的数组来存储分割后的子字符串
            char outer_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
            int outer_index = 0;
            outer_index = parse_record(outer_record, outer_row);

            strlcpy(inner_record, midres->record[j+1], MAX_RECORD_LENGTH);
            char inner_row[MAX_FIELD_NUM][MAX_FIELD_LENGTH];  // 假设每个子字符串不超过 100 个字符，最多分割 100 次
            int inner_index = 0;
            inner_index = parse_record(inner_record, inner_row);

            // printf("%s\n", inner_record);
            // printf("%s\n", outer_row[sortkey_field[0]]);
            // printf("%d\n", atoi(inner_row[sortkey_field[0]]));

            for(int k=0; k<sortKeyNum; k++) {
                if(asc[k]) {  // asc order
                    char* type = getType(sortKey[k]);
                    // printf("type:%s\n",type);
                    if(strcmp(type, "int") == 0 || strcmp(type, "float") == 0) {
                        if(atof(outer_row[sortkey_field[k]]) > atof(inner_row[sortkey_field[k]])) {
                            char temp_record[MAX_RECORD_LENGTH];
                            strlcpy(temp_record, midres->record[j], MAX_RECORD_LENGTH); 
                            strlcpy(midres->record[j], midres->record[j+1], MAX_RECORD_LENGTH);
                            strlcpy(midres->record[j+1], temp_record, MAX_RECORD_LENGTH);
                            break;
                        }else if(atof(outer_row[sortkey_field[k]]) == atof(inner_row[sortkey_field[k]])) {
                            continue;
                        }else {
                            break;
                        }
                    } else {
                        if(strncmp(outer_row[sortkey_field[k]], inner_row[sortkey_field[k]], MAX_FIELD_LENGTH) > 0) {
                            char temp_record[MAX_RECORD_LENGTH];
                            strlcpy(temp_record, midres->record[j], MAX_RECORD_LENGTH);
                            strlcpy(midres->record[j], midres->record[j+1], MAX_RECORD_LENGTH);
                            strlcpy(midres->record[j+1], temp_record, MAX_RECORD_LENGTH);
                            break;
                        }else if(strncmp(outer_row[sortkey_field[k]], inner_row[sortkey_field[k]], MAX_FIELD_LENGTH) == 0) {
                            continue;
                        }else {
                            break;
                        }
                    }
                } else {  // desc order
                    char* type = getType(sortKey[k]);
                    if(strcmp(type, "int") == 0 || strcmp(type, "float") == 0) {
                        if(atof(outer_row[sortkey_field[k]]) < atof(inner_row[sortkey_field[k]])) {
                            char temp_record[MAX_RECORD_LENGTH];
                            strlcpy(temp_record, midres->record[j], MAX_RECORD_LENGTH); 
                            strlcpy(midres->record[j], midres->record[j+1], MAX_RECORD_LENGTH);
                            strlcpy(midres->record[j+1], temp_record, MAX_RECORD_LENGTH);
                            break;
                        }else if(atof(outer_row[sortkey_field[k]]) == atof(inner_row[sortkey_field[k]])) {
                            continue;
                        }else {
                            break;
                        }
                    } else {
                        if(strncmp(outer_row[sortkey_field[k]], inner_row[sortkey_field[k]], MAX_FIELD_LENGTH) < 0) {
                            char temp_record[MAX_RECORD_LENGTH];
                            strlcpy(temp_record, midres->record[j], MAX_RECORD_LENGTH);
                            strlcpy(midres->record[j], midres->record[j+1], MAX_RECORD_LENGTH);
                            strlcpy(midres->record[j+1], temp_record, MAX_RECORD_LENGTH);
                            break;
                        }else if(strncmp(outer_row[sortkey_field[k]], inner_row[sortkey_field[k]], MAX_FIELD_LENGTH) == 0) {
                            continue;
                        }else {
                            break;
                        }
                    }
                }
            }
        }
    }
    //     uint64_t end = get_rdtsc();
    // time += (end - start) / TSC_FREQUENCY;
    for(int i=1; i<midres_cnt; i++) {
        strncpy(result->record[i],midres->record[i], MAX_RECORD_LENGTH);
    }

    return midres_cnt;
}

double calculate_aggr(double a, double b) 
{
    return a*(1-b);
}

int execute_aggregate(int midres_cnt, Page* midres, int groupKeyNum, char (*groupKey)[MAX_FIELD_LENGTH], 
                        int outputNum, char (*output)[MAX_FIELD_LENGTH], Page* result)                             
{
    char inner_fields_record[MAX_RECORD_LENGTH];
    char* fields = midres->record[0];
    char mid_fields[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
    int mid_fields_num = parse_record(fields, mid_fields);

    int* group_fields = (int *)malloc(groupKeyNum * sizeof(int));
    int* output_fields = (int *)malloc(outputNum * sizeof(int));
    // int* order = (int *)malloc(groupKeyNum * sizeof(int));
    int field_cnt = 0;
    int aggr_cnt = -1;
    int aggr_id = 0;

    for(int i=0; i<groupKeyNum; i++) {
        printf("%s\n", groupKey[i]);
        for(int j=0; j<mid_fields_num; j++) {
            if(!strcmp(groupKey[i], mid_fields[j])){
                group_fields[field_cnt] = j;
                field_cnt ++;
            }
        }
    }

    for(int i=0; i<outputNum; i++) {
        // printf("output:%s\n", output[i]);
        strncat(result->record[0], output[i], MAX_FIELD_LENGTH);
        strncat(result->record[0], "|", MAX_FIELD_LENGTH);
        bool flag = false;
        for(int j=0; j<mid_fields_num; j++) {
            if(!strcmp(output[i], mid_fields[j])){
                output_fields[i] = j;
                flag = true;
                break;
            }
        }
        if(!flag) {
            output_fields[i] = aggr_cnt;
            aggr_cnt--;
            aggr_id = i;
        }
    }

    char record[MAX_RECORD_LENGTH];
    char group[MAX_GROUPKEY_NUM][MAX_FIELD_LENGTH] = {0}; 
    char aggr[MAX_GROUPKEY_NUM][MAX_FIELD_LENGTH] = {0}; 

    int result_cnt = 1;
    bool next_group = false;
    for(int i=1; i<midres_cnt; i++){     
        strlcpy(record, midres->record[i], MAX_RECORD_LENGTH);
        // 创建一个足够大的数组来存储分割后的子字符串
        char row[MAX_FIELD_NUM][MAX_FIELD_LENGTH] = {0};  
        int index = parse_record(record, row);
        next_group = false;
        
        // printf("i:%d, %s, %s, %s\n", i, group[0], group[1], group[2], group[3]);
        if(i == 1) {
            for(int j=0; j<outputNum; j++) {
                if(output_fields[j] < 0) {
                    // double aggr_value = calculate_aggr(atof(row[3]), atof(row[4]));
                    int aggr_value = 1;
                    char aggr_str[MAX_FIELD_LENGTH];
                    // snprintf(aggr_str, sizeof(aggr_str), "%f", aggr_value);
                    snprintf(aggr_str, sizeof(aggr_str), "%d", aggr_value);
                    strlcpy(aggr[(-1)*output_fields[j]], aggr_str, MAX_FIELD_LENGTH);
                } else {
                    strlcpy(group[output_fields[j]], row[output_fields[j]], MAX_FIELD_LENGTH);
                }
            }
            // printf("i:%d, %s, %s, %s, %s\n", i, group[0], group[1], group[2], aggr[1]);
            continue;
        }

        for(int j=0; j<groupKeyNum; j++){
            // printf("%s, %s, %d\n", row[group_fields[j]], group[j], strcmp(row[group_fields[j]], group[j]));
            if(strcmp(row[group_fields[j]], group[j])) {
                // strlcpy(group[j], row[group_fields[j]], MAX_FIELD_LENGTH);
                next_group = true;
                break;
            } 
        }
        if(!next_group) {
            // double aggr_value = calculate_aggr(atof(row[3]), atof(row[4]));
            // aggr_value += atof(aggr[1]);
            int aggr_value = atoi(aggr[1]) + 1;
            char aggr_str[MAX_FIELD_LENGTH];
            // snprintf(aggr_str, sizeof(aggr_str), "%f", aggr_value);
            snprintf(aggr_str, sizeof(aggr_str), "%d", aggr_value);
            strlcpy(aggr[1], aggr_str, MAX_FIELD_LENGTH);
            // printf("i:%d, %s, %s, %s\n", i, group[0], group[1], group[2], aggr[1]);
        } else {
            for(int j=0; j<outputNum; j++) {
                if(output_fields[j] < 0) {
                    strncat(result->record[result_cnt], aggr[(-1)*output_fields[j]], MAX_FIELD_LENGTH);
                    strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                    // double aggr_value = calculate_aggr(atof(row[3]), atof(row[4]));
                    int aggr_value = 1;
                    // printf("%f\n", aggr_value);
                    char aggr_str[MAX_FIELD_LENGTH];
                    // snprintf(aggr_str, sizeof(aggr_str), "%f", aggr_value);
                    snprintf(aggr_str, sizeof(aggr_str), "%d", aggr_value);
                    strlcpy(aggr[(-1)*output_fields[j]], aggr_str, MAX_FIELD_LENGTH);
                } else {
                    strncat(result->record[result_cnt], group[output_fields[j]], MAX_FIELD_LENGTH);
                    strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                    strlcpy(group[output_fields[j]], row[output_fields[j]], MAX_FIELD_LENGTH);
                }
            }
            // printf("i:%d, %s, %s, %s\n", i, group[0], group[1], group[2], aggr[1]);
            result_cnt++;
        }
        if(i == midres_cnt-1) {
            for(int j=0; j<outputNum; j++) {
                if(output_fields[j] < 0) {
                    strncat(result->record[result_cnt], aggr[(-1)*output_fields[j]], MAX_FIELD_LENGTH);
                    strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                } else {
                    strncat(result->record[result_cnt], group[output_fields[j]], MAX_FIELD_LENGTH);
                    strncat(result->record[result_cnt], "|", MAX_FIELD_LENGTH);
                }
            }
            result_cnt++;
        }
        // printf("%s\n", group[0]);
    }
    return result_cnt;
}

void print_jsonnode(JsonNode* node) {
    if(node == NULL) {
        return;
    }
    print_jsonnode(node->left);

    printf("Jsonnode type:%s\n", node->nodeType);
    if(!strcmp(node->nodeType, "join")) {
        printf("filter:%s\n", node->joinFilter);
        for(int i=0; i<node->outputNum; i++) {
            printf("output[%d]:%s\n", i, node->output[i]);
        }
    } else if(!strcmp(node->nodeType, "scan")) {
        printf("relation name:%s\n", node->relName);
        printf("alias:%s\n", node->alias);
        for(int i=0; i<node->outputNum; i++) {
            printf("output[%d]:%s\n", i, node->output[i]);
        }
    }
    
    print_jsonnode(node->right);
}

void extract_join_col(char *input, char *join_col1, char *join_col2) 
{
    // size_t len = strlen(input);
    // // 判断首尾是否为括号
    // if (input[0] == '(' && input[len - 1] == ')') {
    //     // 将字符串整体左移一位，并在末尾添加空字符
    //     memmove(input, input + 1, len - 1);
    //     input[len - 2] = '\0'; // 设置新的字符串结尾
    // }

    // const char *start1, *end1, *start2;
    // start1 = strchr(input, '.');
    // end1 = strchr(input, '=');
    
    // if (start1 != NULL && end1 != NULL) {
    //     start1++;
    //     end1--;
        
    //     start2 = strchr(end1 + 1, '.');
        
    //     if (start2 != NULL) {
    //         size_t length1 = end1 - start1;
    //         size_t length2 = strlen(start2 + 1); 
            
    //         strncpy(join_col1, start1, length1);
    //         strncpy(join_col2, start2 + 1, length2); 
    //         join_col1[length1] = '\0';
    //         join_col2[length2] = '\0';
    //     }
    // }

    char *col1_start = NULL;
    char *col2_start = NULL;

    // 定位第一个 '.' 后的字符 (user_table.xxx)
    char *first_dot = strchr(input, '.');
    if (first_dot) {
        col1_start = first_dot + 1; // 跳过 '.'
        char *col1_end = strchr(col1_start, ')'); // 找到第一个 ')'
        if (col1_end) {
            strncpy(join_col1, col1_start, col1_end - col1_start);
            join_col1[col1_end - col1_start] = '\0';
        }
    }

    // 定位第二个 '.' 后的字符 (file_data.xxx)
    char *second_dot = strchr(first_dot + 1, '.');
    if (second_dot) {
        col2_start = second_dot + 1; // 跳过 '.'
        const char *col2_end = strchr(col2_start, ')'); // 找到第一个 ')'
        if (col2_end) {
            strncpy(join_col2, col2_start, col2_end - col2_start);
            join_col2[col2_end - col2_start] = '\0';
        }
    }
}

void malloc_array(char** result) 
{
    result = (char **)malloc(MAX_ROW_NUM * sizeof(char *));
    if (result == NULL) {
        printf("内存分配失败1\n");
        return;
    }
    for (int i = 0; i < MAX_ROW_NUM; i++) {
        result[i] = (char *)malloc(MAX_RECORD_LENGTH * sizeof(char));
        if (result[i] == NULL) {
            printf("内存分配失败2\n");
            return;
        }
    }
}

Page* parse_jsonnode(JsonNode* node, int* row_num) {
    if(node == NULL) {
        return NULL;
    }

    Page* left_res = parse_jsonnode(node->left, row_num);
    int left_num = *row_num;
    Page* right_res = parse_jsonnode(node->right, row_num);
    int right_num = *row_num;


    if(!strcmp(node->nodeType, "scan")) {
        char sql[MAX_SQL_LENGTH] = "SELECT ";
        for(int i=0; i<node->outputNum; i++) {
            strncat(sql, node->output[i], MAX_SQL_LENGTH);
            if(i != node->outputNum-1) {
                strncat(sql, ", ", MAX_SQL_LENGTH);
            }
        }
        strncat(sql, " FROM ", MAX_SQL_LENGTH);
        strncat(sql, node->relName, MAX_SQL_LENGTH);
        strncat(sql, " ", MAX_SQL_LENGTH);
        strncat(sql, node->alias, MAX_SQL_LENGTH);
        // printf("filter: %s, %d\n", node->joinFilter, strlen(node->joinFilter));
        if(node->joinFilter != NULL && strlen(node->joinFilter) != 0) {
            strncat(sql, " WHERE ", MAX_SQL_LENGTH);
            strncat(sql, node->joinFilter, MAX_SQL_LENGTH);
        }
        strlcpy(node->sqlStatement, sql, MAX_SQL_LENGTH);
        // printf("%s\n", sql);
        return NULL;
    } else if (!strcmp(node->nodeType, "join")) {
        if(!strcmp(node->left->nodeType, "scan")) {
            if(!strcmp(node->right->nodeType, "scan")) {
                if(left_res!= NULL || right_res != NULL) {
                    printf("error!\n");
                }
                char sql1[MAX_SQL_LENGTH];
                char sql2[MAX_SQL_LENGTH];
                strlcpy(sql1, node->left->sqlStatement, MAX_SQL_LENGTH);
                strlcpy(sql2, node->right->sqlStatement, MAX_SQL_LENGTH);

                char filter[MAX_FILTER_LENGTH];
                char join_col1[MAX_FIELD_LENGTH];
                char join_col2[MAX_FIELD_LENGTH];
                strlcpy(filter, node->joinFilter, MAX_FILTER_LENGTH);
                extract_join_col(filter, join_col1, join_col2);

                int id1 = getTableId(node->left->relName);
                int id2 = getTableId(node->right->relName);
                printf("table id: %d, %d\n", id1, id2);

                if(strlen(node->left->joinFilter) == 0) {
                    verifyFlags[id1] = true;
                }

                if(strlen(node->right->joinFilter) == 0) {
                    verifyFlags[id2] = true;
                }

                Page* mid_res = (Page*)malloc(sizeof(Page)); 
                if (mid_res != NULL) {
                    memset(mid_res, 0, sizeof(Page));
                }
                *row_num = execute_join(sql1, sql2, join_col1, join_col2, id1, id2, node->outputNum, node->output, mid_res);
                printf("row num1 is: %d\n", *row_num);
                for(int i=0;i<*row_num;i++) {
                    printf("%s\n", mid_res->record[i]);
                }
                return mid_res;
            } else if(!strcmp(node->right->nodeType, "join")) {
                // todo
            }
        } else if(!strcmp(node->left->nodeType, "join")) {
            if(!strcmp(node->right->nodeType, "scan")) {
                char sql[MAX_SQL_LENGTH];
                strlcpy(sql, node->right->sqlStatement, MAX_SQL_LENGTH);
                char filter[MAX_FILTER_LENGTH];
                char join_col1[MAX_FIELD_LENGTH];
                char join_col2[MAX_FIELD_LENGTH];
                strlcpy(filter, node->joinFilter, MAX_FILTER_LENGTH);
                extract_join_col(filter, join_col1, join_col2);

                int id = getTableId(node->right->relName);
                printf("table id: %d\n", id);

                Page* mid_res = (Page*)malloc(sizeof(Page));
                if (mid_res != NULL) {
                    memset(mid_res, 0, sizeof(Page));
                }
                *row_num = execute_join_with_midres(left_num, left_res, sql, join_col1, join_col2, id, node->outputNum, node->output, mid_res);
                printf("row num2 is: %d\n", *row_num);
                return mid_res;
            } else if(!strcmp(node->right->nodeType, "join")) {
                // todo
            }
        }
    } else if (!strcmp(node->nodeType, "sort")) {
        printf("sortkey nums:%d\n", node->sortKeyNum);
        Page* mid_res = (Page*)malloc(sizeof(Page)); 
        if (mid_res != NULL) {
            memset(mid_res, 0, sizeof(Page));
        }
        *row_num = execute_sort(left_num, left_res, node->sortKeyNum, node->sortKey, node->outputNum, node->output, mid_res);
        for(int i=0;i<*row_num;i++) {
            printf("%s\n", mid_res->record[i]);
        }
        return mid_res;
    } else if (!strcmp(node->nodeType, "aggregate")) {
        for(int i=0; i<node->groupKeyNum; i++) {
            printf("%s\n", node->groupKey[i]);
        }

        Page* mid_res = (Page*)malloc(sizeof(Page)); 
        if (mid_res != NULL) {
            memset(mid_res, 0, sizeof(Page));
        }
        *row_num = execute_aggregate(left_num, left_res, node->groupKeyNum, node->groupKey, node->outputNum, node->output, mid_res);
        printf("res nums:%d\n", *row_num);
        return mid_res;
    } 
}

void enclave_generate_sql(JsonNode* node, size_t len) 
{
    printf("into enclave\n");
    initTypeDict();
    JsonNode *current = node;
    // print_jsonnode(current);
    // malloc_array();

    int final_num = 0;
    Page* final_res = parse_jsonnode(current, &final_num);

    printf("final result num is %d:\n", final_num-1);
    for(int i=0; i<final_num; i++){
        printf("%s\n", final_res->record[i]);
        ocall_put_result(final_res->record[i], MAX_RECORD_LENGTH);
    }
    printf("time :%lf s\n",time);
    // free_array();
    // verify();

}

void enclave_process_row(const char* data) {
    printf("flag");
    printf("Enclave processed data: %s\n", data);
}